
from functools import wraps

def show_before_after(func):
   
    @wraps(func)
    def sba(*args,**kwargs):
        print func.__name__
        func(*args,**kwargs)
        print "fine "
    return sba

from multiprocessing import Process
from functools import wraps

def run_async(func):
	"""
		run_async(func)
			function decorator, intended to make "func" run in a separate
			thread (asynchronously).
			Returns the created Thread object

			E.g.:
			@run_async
			def task1():
				do_something

			@run_async
			def task2():
				do_something_too

			t1 = task1()
			t2 = task2()
			...
			t1.join()
			t2.join()
	"""
	
	@wraps(func)
	def async_func(*args, **kwargs):
		func_hl = Process(target = func, args = args, kwargs = kwargs)
		func_hl.start()
		
		return func_hl
        
	
	return async_func

from threading import Thread
def run_async_threaded(func):
	"""
		run_async(func)
			function decorator, intended to make "func" run in a separate
			thread (asynchronously).
			Returns the created Thread object

			E.g.:
			@run_async
			def task1():
				do_something

			@run_async
			def task2():
				do_something_too

			t1 = task1()
			t2 = task2()
			...
			t1.join()
			t2.join()
	"""
	
	@wraps(func)
	def async_func(*args, **kwargs):
		func_hl = Thread(target = func, args = args, kwargs = kwargs)
		func_hl.start()
		
		return func_hl
        
	
	return async_func

#~ def run_async2(func):
    #~ class async_class(object):
        #~ func_hl=None
            #~ 
        #~ @wraps(func)
        #~ def __call__(self,*args,**kwargs):
            #~ print 'called'
            #~ self.func_hl = Process(target = func, args = args, kwargs = kwargs)
            #~ self.func_hl.start()
            #~ 
        #~ def terminate(self):
            #~ self.func_hl.terminate()
            #~ 
    #~ return async_class()

class mynotification(object):
    """
        Represent a desktop notification.
    """
    def __init__(self,icon_uri, app_name):
        self.app_name=app_name
        self.icon_uri=icon_uri
        self.showed=False
        
        # init pynotify 
        import  pynotify as pn
        pn.init(self.app_name)
        
        # setup notification
        self.showed=True
        self.n=pn.Notification(self.app_name,' ',self.icon_uri)
        self.n.set_category("Network")
        self.n.set_timeout(pn.EXPIRES_DEFAULT)
        self.showed=True
        
    #~ @run_async_threaded
    def show(self,msg,new_icon=None):
        """
            Represent a desktop notification.
            This method shows or updates it
            the optional new_icon parameter sets a temporary new icon
        """
        
        if new_icon:
            self.n.update( self.app_name,msg,new_icon)
        else:
            self.n.update( self.app_name,msg,self.icon_uri)
        # http://stackoverflow.com/questions/5623289/pynotify-runs-fine-interactively-but-crashes-when-run-programmatically-on-fedor
        try:
            Thread(target =self.n.show).start()
        except Exception,e:
            Thread(target =self.n.show).start()
            print e

